`timescale 1ns / 1ps
/*
 Copyright 2020 Sean Xiao, jxzsxsp@qq.com
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 
 http://www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

module csr_mip
(
    input sys_clk,

    input i_sft_irq,
    input i_tmr_irq,
    input i_ext_irq,

    input [ 11: 0 ] i_csr_addr,
    input [ 31: 0 ] i_csr_val,
    input i_csr_wen,
    
    output [ 31: 0 ] o_mip,

    input rst_n
);

/*
mip:   Machine Interrupt Pending Registers   WR

XLEN-1   12   11     10     9      8      7      6      5      4      3      2      1      0     
------------------------------------------------------------------------------------------------
WIRI       | MEIP | WIRI | SEIP | UEIP | MTIP | WIRI | STIP | UTIP | MSIP | WIRI | SSIP | USIP |
------------------------------------------------------------------------------------------------


*/

//0x044 URW uip User interrupt pending.
//  We dont support delegation scheme, so no need to support the uip
//0x344 MRW o_mip Machine interrupt pending
wire sel_mip = ( i_csr_addr == 12'h344 );
wire we_mip = sel_mip & i_csr_wen;

// The MxIP is read-only
wire meip_r;
wire msip_r;
wire mtip_r;

//`define REG_LATCH
`ifdef REG_LATCH
    fii_dffr #(1) meip_dffr (i_ext_irq, meip_r, sys_clk, rst_n);
    fii_dffr #(1) msip_dffr (i_sft_irq, msip_r, sys_clk, rst_n);
    fii_dffr #(1) mtip_dffr (i_tmr_irq, mtip_r, sys_clk, rst_n);
`else
    assign meip_r = i_ext_irq;
    assign msip_r = i_sft_irq;
    assign mtip_r = i_tmr_irq;
`endif

wire [ 31: 0 ] ip_r;
assign ip_r[ 31: 12 ] = 20'b0;
assign ip_r[ 11 ]     = meip_r;
assign ip_r[ 10: 8 ]  = 3'b0;
assign ip_r[ 7 ]      = mtip_r;
assign ip_r[ 6: 4 ]   = 3'b0;
assign ip_r[ 3 ]      = msip_r;
assign ip_r[ 2: 0 ]   = 3'b0;

assign o_mip = ip_r;
//
endmodule
